#pragma once
#include <iostream>
#include <cstring>
#include <unistd.h>
#include <sys/epoll.h>
#include <set>
#include "../logsystem/logger/log.h"
// 封装epoll

namespace EpollerModule
{
    enum Error
    {
        CREATE_ERROR = -1,
    };
    const int gsize = 32;
    class Epoller
    {
    public:
        Epoller()
        {
        }
        void InitEpoll()
        {
            // 构建ep模型
            _epfd = ::epoll_create(gsize);
            if (_epfd == -1)
            {
                // 创建失败
                ELOG("epoll 模型创建失败!%d:%s", errno, strerror(errno));
                exit(CREATE_ERROR);
            }
            ILOG("epoll模型创建成功!返回文件描述符是:%d", _epfd);
        }

        void AddEvent(int sockfd, uint32_t event)
        {
            struct epoll_event revent;
            revent.data.fd = sockfd; // 这个是给用户看的，便于识别是哪个文件描述符
            revent.events = event;
            int n = ::epoll_ctl(_epfd, EPOLL_CTL_ADD, sockfd, &revent);
            _list.insert(sockfd);
            // 判断
            if (n == -1)
            {
                WLOG("添加epoll事件失败!");
                _list.erase(sockfd);
            }
        }

        void DeletEvent(int sockfd)
        {
            _list.erase(sockfd);
            int n = epoll_ctl(_epfd, EPOLL_CTL_DEL, sockfd, nullptr);
            if (n < 0)
            {
                WLOG("取消%d描述符关心事件失败", sockfd);
            }
        }

        int EpollWait(struct epoll_event *events, int maxevents, int timeout)
        {
            int n = epoll_wait(_epfd, events, maxevents, timeout);
            return n;
        }
        ~Epoller()
        {
            if (_epfd >= 0)
            {
                close(_epfd);
                ILOG("释放epoll模型,fd:%d...", _epfd);
            }
        }

        void DebugFdList()
        {
            std::cout << "fd_list:";
            for (auto &x : _list)
            {
                std::cout << x << " ";
            }
            std::cout << std::endl;
        }

    private:
        int _epfd;
        std::set<int> _list;
    };
}